using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TxTReader.Core
{
    /// <summary>
    /// 文本行数据
    /// </summary>
    public class TextLine
    {
        public int LineNumber { get; set; }
        public string Content { get; set; } = string.Empty;
        public long FilePosition { get; set; }
        public int Length { get; set; }
    }

    /// <summary>
    /// 文件读取核心
    /// </summary>
    public class FileReader : IDisposable
    {
        private readonly int _chunkSize;
        private readonly int _maxCacheSize;
        private readonly Dictionary<int, TextLine> _lineCache;
        private readonly Queue<int> _cacheOrder;
        private readonly Dictionary<int, long> _linePositions; // 行号到文件位置的映射
        private FileStream? _fileStream;
        private StreamReader? _streamReader;
        private Encoding _currentEncoding = Encoding.UTF8;
        private long _totalLines = -1;
        private bool _disposed = false;
        private bool _linePositionsBuilt = false;

        public string FilePath { get; private set; } = string.Empty;
        public Encoding CurrentEncoding => _currentEncoding;
        public long TotalLines => _totalLines;
        public bool IsFileOpen => _fileStream != null && !_disposed;

        public event EventHandler<EncodingChangedEventArgs>? EncodingChanged;
        public event EventHandler<FileOpenedEventArgs>? FileOpened;

        public FileReader(int chunkSize = 1000, int maxCacheSize = 100)
        {
            _chunkSize = chunkSize;
            _maxCacheSize = maxCacheSize;
            _lineCache = new Dictionary<int, TextLine>();
            _cacheOrder = new Queue<int>();
            _linePositions = new Dictionary<int, long>();
        }

        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="encoding">指定编码，null表示自动检测</param>
        public async Task<bool> OpenFileAsync(string filePath, Encoding? encoding = null)
        {
            try
            {
                CloseFile();

                if (!File.Exists(filePath))
                    return false;

                FilePath = filePath;

                // 检测编码
                if (encoding == null)
                {
                    _currentEncoding = EncodingDetector.DetectFileEncoding(filePath);
                }
                else
                {
                    _currentEncoding = encoding;
                }

                // 打开文件流
                _fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                _streamReader = new StreamReader(_fileStream, _currentEncoding, true);

                // 计算总行数
                _totalLines = await CountLinesAsync();

                // 清空缓存
                _lineCache.Clear();
                _cacheOrder.Clear();

                OnFileOpened(new FileOpenedEventArgs(filePath, _currentEncoding, _totalLines));
                return true;
            }
            catch (Exception ex)
            {
                CloseFile();
                throw new FileReaderException($"打开文件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 重新加载文件（使用新编码）
        /// </summary>
        /// <param name="encoding">新编码</param>
        public async Task<bool> ReloadWithEncodingAsync(Encoding encoding)
        {
            if (string.IsNullOrEmpty(FilePath))
                return false;

            var oldEncoding = _currentEncoding;
            _currentEncoding = encoding;

            try
            {
                await OpenFileAsync(FilePath, encoding);
                OnEncodingChanged(new EncodingChangedEventArgs(oldEncoding, encoding));
                return true;
            }
            catch
            {
                _currentEncoding = oldEncoding;
                return false;
            }
        }

        /// <summary>
        /// 获取指定行
        /// </summary>
        /// <param name="lineNumber">行号（从1开始）</param>
        /// <returns>文本行</returns>
        public async Task<TextLine?> GetLineAsync(int lineNumber)
        {
            if (!IsFileOpen || lineNumber < 1 || lineNumber > _totalLines)
                return null;

            // 检查缓存
            if (_lineCache.TryGetValue(lineNumber, out var cachedLine))
                return cachedLine;

            // 从文件读取
            var line = await ReadLineFromFileAsync(lineNumber);
            if (line != null)
            {
                AddToCache(lineNumber, line);
            }

            return line;
        }

        /// <summary>
        /// 获取多行
        /// </summary>
        /// <param name="startLine">起始行号</param>
        /// <param name="count">行数</param>
        /// <returns>文本行列表</returns>
        public async Task<List<TextLine>> GetLinesAsync(int startLine, int count)
        {
            var lines = new List<TextLine>();
            
            for (int i = 0; i < count; i++)
            {
                var lineNumber = startLine + i;
                var line = await GetLineAsync(lineNumber);
                if (line != null)
                {
                    lines.Add(line);
                }
                else
                {
                    break;
                }
            }

            return lines;
        }

        /// <summary>
        /// 从文件读取指定行（简化版本）
        /// </summary>
        /// <param name="lineNumber">行号</param>
        /// <returns>文本行</returns>
        private async Task<TextLine?> ReadLineFromFileAsync(int lineNumber)
        {
            if (_streamReader == null || _fileStream == null || _disposed)
                return null;

            try
            {
                // 使用简单的方法：每次都从头开始读取
                return await ReadLineFromFileAsyncLegacy(lineNumber);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 从文件读取指定行（原始方法）
        /// </summary>
        /// <param name="lineNumber">行号</param>
        /// <returns>文本行</returns>
        private async Task<TextLine?> ReadLineFromFileAsyncLegacy(int lineNumber)
        {
            if (_streamReader == null || _fileStream == null || _disposed)
                return null;

            try
            {
                // 重置到文件开头
                _streamReader.DiscardBufferedData();
                _fileStream.Position = 0;

                var currentLine = 1;
                var position = _fileStream.Position;

                while (currentLine < lineNumber)
                {
                    // 检查是否已被释放
                    if (_disposed || _streamReader == null || _fileStream == null)
                        return null;

                    var line = await _streamReader.ReadLineAsync();
                    if (line == null)
                        return null;

                    currentLine++;
                    position = _fileStream.Position;
                }

                // 检查是否已被释放
                if (_disposed || _streamReader == null || _fileStream == null)
                    return null;

                // 读取目标行
                var targetLine = await _streamReader.ReadLineAsync();
                if (targetLine == null)
                    return null;

                return new TextLine
                {
                    LineNumber = lineNumber,
                    Content = targetLine,
                    FilePosition = position,
                    Length = targetLine.Length
                };
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 计算文件总行数并构建行位置索引
        /// </summary>
        /// <returns>总行数</returns>
        private async Task<long> CountLinesAndBuildIndexAsync()
        {
            if (_streamReader == null)
                return 0;

            try
            {
                _streamReader.DiscardBufferedData();
                _fileStream!.Position = 0;

                _linePositions.Clear();
                long lineCount = 0;
                var position = _fileStream.Position;

                string? line;
                while ((line = await _streamReader.ReadLineAsync()) != null)
                {
                    lineCount++;
                    _linePositions[(int)lineCount] = position;
                    position = _fileStream.Position;
                }

                _linePositionsBuilt = true;
                return lineCount;
            }
            catch
            {
                _linePositionsBuilt = false;
                return 0;
            }
        }

        /// <summary>
        /// 计算文件总行数（不构建索引）
        /// </summary>
        /// <returns>总行数</returns>
        private async Task<long> CountLinesAsync()
        {
            if (_streamReader == null)
                return 0;

            try
            {
                _streamReader.DiscardBufferedData();
                _fileStream!.Position = 0;

                long lineCount = 0;
                while (await _streamReader.ReadLineAsync() != null)
                {
                    lineCount++;
                }

                return lineCount;
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 添加到缓存
        /// </summary>
        /// <param name="lineNumber">行号</param>
        /// <param name="line">文本行</param>
        private void AddToCache(int lineNumber, TextLine line)
        {
            // 如果缓存已满，移除最旧的项
            if (_lineCache.Count >= _maxCacheSize)
            {
                if (_cacheOrder.Count > 0)
                {
                    var oldestLineNumber = _cacheOrder.Dequeue();
                    _lineCache.Remove(oldestLineNumber);
                }
            }

            _lineCache[lineNumber] = line;
            _cacheOrder.Enqueue(lineNumber);
        }

        /// <summary>
        /// 关闭文件
        /// </summary>
        public void CloseFile()
        {
            _streamReader?.Dispose();
            _fileStream?.Dispose();
            _streamReader = null;
            _fileStream = null;
            _totalLines = -1;
            _lineCache.Clear();
            _cacheOrder.Clear();
            _linePositions.Clear();
            _linePositionsBuilt = false;
        }

        /// <summary>
        /// 触发文件打开事件
        /// </summary>
        protected virtual void OnFileOpened(FileOpenedEventArgs e)
        {
            FileOpened?.Invoke(this, e);
        }

        /// <summary>
        /// 触发编码改变事件
        /// </summary>
        protected virtual void OnEncodingChanged(EncodingChangedEventArgs e)
        {
            EncodingChanged?.Invoke(this, e);
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                CloseFile();
                _disposed = true;
            }
        }
    }

    /// <summary>
    /// 文件打开事件参数
    /// </summary>
    public class FileOpenedEventArgs : EventArgs
    {
        public string FilePath { get; }
        public Encoding Encoding { get; }
        public long TotalLines { get; }

        public FileOpenedEventArgs(string filePath, Encoding encoding, long totalLines)
        {
            FilePath = filePath;
            Encoding = encoding;
            TotalLines = totalLines;
        }
    }

    /// <summary>
    /// 编码改变事件参数
    /// </summary>
    public class EncodingChangedEventArgs : EventArgs
    {
        public Encoding OldEncoding { get; }
        public Encoding NewEncoding { get; }

        public EncodingChangedEventArgs(Encoding oldEncoding, Encoding newEncoding)
        {
            OldEncoding = oldEncoding;
            NewEncoding = newEncoding;
        }
    }

    /// <summary>
    /// 文件读取异常
    /// </summary>
    public class FileReaderException : Exception
    {
        public FileReaderException(string message) : base(message) { }
        public FileReaderException(string message, Exception innerException) : base(message, innerException) { }
    }
}
